// popable.js - popable event listeners

var __popable = {

'elements': {},

'disable': function(e) { e.stopPropagation(); e.preventDefault(); },

'id_seq': 100,

'gc': {
	'gc': function() {
		for( var el in this.elements ) {
			if( !document.querySelector("[popable_id='"+this.elements[el].popable_id+"']") ) delete this.elements[el];
		}
		this.handler  = null;
		this.ct = 1000;
	},
	'ct': 1000,
	'handler': null,
	'start': function() {
		if( this.ct-- > 0 ) return;
		if( this.handler ) return;
		this.handler = setTimeout( gc, 30000 );
	}
}
};

Element.prototype.addPopableEventListener = function(evt,func,tf) {
	if( tf==undefined ) tf = true;
	// set our own id
	if( this.getAttribute('popable_id')==undefined ) this.setAttribute('popable_id',__popable.id_seq++);
	var popable_id = this.getAttribute('popable_id');
	if( this.getAttribute('popable_'+evt)==undefined ) this.setAttribute('popable_'+evt,0);
	var level = this.getAttribute('popable_'+evt);
	// add event to popable
	if( __popable.elements[popable_id]==undefined ) __popable.elements[popable_id] = {};
	if( __popable.elements[popable_id][evt]==undefined ) __popable.elements[popable_id][evt] = {};
	if( __popable.elements[popable_id][evt][level]==undefined ) __popable.elements[popable_id][evt][level] = [];
	__popable.elements[popable_id][evt][level].push( { 'func': func, 'bubble': tf } );
	// add to actual listener
	if( func ) this.addEventListener(evt,func,tf);
	// gc
	__popable.gc.start();
}

Element.prototype.pushPopableEventListener = function(evt,func,tf) {
	if( tf==undefined ) tf = true;
	// if we do not have an event registered, do nothing
	if( !('popable_id' in this.attributes) || !('popable_'+evt in this.attributes) ) return;
	// set our own id
	var popable_id = this.getAttribute('popable_id');
	this.setAttribute('popable_'+evt,parseInt(this.getAttribute('popable_'+evt))+1);
	var level = parseInt(this.getAttribute('popable_'+evt));
	// if nothing to push, ignore
	if( !('popable_id' in __popable.elements) || !(evt in __popable_id.elements[popable_id]) || !((level-1) in __popable.elements[popable_id][evt])
		|| ! __popable_id.elements[popable_id][(level-1)].length ) return;
	// add event to popable
	if( __popable.elements[popable_id]==undefined ) __popable.elements[popable_id] = {};
	if( __popable.elements[popable_id][evt]==undefined ) __popable.elements[popable_id][evt] = {};
	if( __popable.elements[popable_id][evt][level]==undefined ) __popable.elements[popable_id][evt][level] = [];
	__popable.elements[popable_id][evt][level].push( { 'func': func, 'bubble': tf } );
	// remove existent listeners
	if( __popable.elements[popable_id][evt][(level-1)] ) 
	for( var i=0; i<__popable.elements[popable_id][evt][level-1].length; i++ ) {
		var el = __popable.elements[popable_id][evt][level-1][i];
		console.log( 'removing '+evt+'.'+(level-1)+', func='+el.func );
		if( el.func ) this.removeEventListener(evt,el.func,el.bubble);
	}
	// add new to actual listener
	this.addEventListener(evt,func,tf);
	// gc
	__popable.gc.start();
}

Element.prototype.popPopableEventListener = function(evt) {
	if( tf==undefined ) tf = true;
	// if we do not have an event registered, do nothing
	if( !('popable_id' in this.attributes) || !('popable_'+evt in this.attributes) ) return;
	// set our own id
	var popable_id = this.getAttribute('popable_id');
	this.setAttribute('popable_'+evt,parseInt(this.getAttribute('popable_'+evt))-1);
	var level = parseInt(this.getAttribute('popable_'+evt));
	// event to pop
	if( __popable.elements[popable_id][evt][(level+1)] ) {
		for( var i=0; i<__popable.elements[popable_id][evt][level+1].length; i++ ) {
			var el = __popable.elements[popable_id][evt][level+1][i];
			console.log( 'removing '+evt+'.'+(level+1)+', func='+el.func );
			if( el.func ) this.removeEventListener(evt,el.func,el.bubble);
		}
		delete __popable.elements[popable_id][evt][(level+1)];
	}
	// add new to actual listener
	if( __popable.elements[popable_id][evt][(level)] ) 
	for( var i=0; i<__popable.elements[popable_id][evt][level].length; i++ ) {
		var el = __popable.elements[popable_id][evt][level][i];
		console.log( 'adding '+evt+'.'+(level)+', func='+el.func );
		if( el.func ) this.addEventListener(evt,el.func,el.bubble);
	}
	// gc
	__popable.gc.start();
}

Element.prototype.removePopableEventListener = function(evt,func,tf) {
	if( tf==undefined ) tf = true;
	// set our own id
	if( ('popable_id' in this.attributes) && ('popable_'+evt in this.attributes) ) {
		var popable_id = this.getAttribute('popable_id');
		var level = parseInt(this.getAttribute('popable_'+evt));
		// listener to remove
		if( __popable.elements[popable_id][evt][level] ) 
		for( var i=0; i<__popable.elements[popable_id][evt][level].length; i++ ) {
			var el = __popable.elements[popable_id][evt][level][i];
			if( el.func == func && el.bubble == tf ) {
				console.log( 'removing '+evt+'.'+(level)+', func='+el.func );
				__popable.elements[popable_id][evt][level] =  __popable.elements[popable_id][evt][level].splice(i,1);
				break;
			}
		}
		// gc
		__popable.gc.start();
	}
	// remove actual listener
	if( func ) this.removeEventListener(evt,func,tf);
}

